package com.gcxy.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.word.WordUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gcxy.constant.PermissionConst;
import com.gcxy.core.PageVO;
import com.gcxy.core.R;
import com.gcxy.dto.evaluate.EvaluateExcelDTO;
import com.gcxy.dto.evaluate.UpdateEvaluateDTO;
import com.gcxy.dto.export.DownloadFileDTO;
import com.gcxy.dto.student.ScheduledTasksDTO;
import com.gcxy.dto.weekly.UpdateWeeklyDTO;
import com.gcxy.dto.weekly.WeeklyEvaluateDTO;
import com.gcxy.dto.weekly.WeeklyPageDTO;
import com.gcxy.dto.weekly.WeeklyReviewDTO;
import com.gcxy.entity.*;
import com.gcxy.mapper.WeeklyMapper;
import com.gcxy.service.*;
import com.gcxy.utils.*;
import com.gcxy.vo.role.RoleVO;
import com.gcxy.vo.user.UserVO;
import com.gcxy.vo.weekly.ProjectVO;
import com.gcxy.vo.weekly.WeeklyAppraiseVO;
import com.gcxy.vo.weekly.WeeklyEvaluateVO;
import com.gcxy.vo.weekly.WeeklyPageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.gcxy.constant.StringConst.*;
import static com.gcxy.enums.ResultCodeEnum.DB_GET_DATA_FAIL;

/**
 * <p>
 * 周报信息 服务实现类
 * </p>
 *
 * @author Huang先森
 * @since 2024-07-22
 */
@Slf4j
@Service
public class WeeklyServiceImpl extends ServiceImpl<WeeklyMapper, Weekly> implements WeeklyService {

    @Autowired
    private SemesterService semesterService;

    @Autowired
    private WeeklyProjectService weeklyProjectService;

    @Autowired
    private StudentTeacherService studentTeacherService;

    @Autowired
    private UserService userService;

    @Autowired
    private AppraiseService appraiseService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private EvaluateService evaluateService;

    @Autowired
    private ScheduledTasks scheduledTasks;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private AgencyService agencyService;

    @Autowired
    private ClazzService clazzService;

    @Autowired
    private PositionService positionService;

    @Autowired
    private UserProjectService userProjectService;

    /**
     * 定时生成周报
     *
     * @param scheduledTasksDTO
     * @return
     */
    @Override
    public R<?> addWeeklyScheduled(ScheduledTasksDTO scheduledTasksDTO) {
        UserVO userInfo = userService.getUserInfo();
        if (ObjectUtils.isEmpty(userInfo)) {
            return R.Failed("用户信息获取失败");
        }
        Agency agency = agencyService.getById(scheduledTasksDTO.getAgencyId());
        if (ObjectUtils.isEmpty(agency)) {
            return R.Failed("当前需要调整生成周报任务的组织机构不存在");
        }
        agency.setHasWeeklyScheduled(scheduledTasksDTO.getStatues());
        boolean update = agencyService.updateById(agency);
        if (!update) {
            return R.Failed("调整生成周报任务失败");
        }
        log.info("组织机构更新成功");
        return R.Success();
    }

    /**
     * 手动执行定时任务
     */
    @Override
    public void manualExecutionScheduled() {
        log.info("手动执行定时任务开始。。。。。。");
        scheduledTasks.addWeeklyEvaluate();
        scheduledTasks.addGuidance();
        log.info("手动执行定时任务结束。。。。。。");
    }

    /**
     * 生成周报
     *
     * @param agencyId
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void addWeekly(Integer agencyId) {
        Semester semester = semesterService.getCurrentSemester();
        if (ObjectUtils.isEmpty(semester)) {
            throw new RuntimeException("组织{" + agencyId + "}当前时间不需要生成周报");
        }
        //获取当前学期内组织下的学生信息
        List<StudentTeacher> studentTeacherList = studentTeacherService.getStudentBySemesterId(semester.getId(), agencyId);
        if (CollectionUtils.isEmpty(studentTeacherList)) {
            throw new RuntimeException("组织{" + agencyId + "}当前学期内没有学生需要填写周报");
        }
        //获取当前周数
        Integer weekNum = semesterService.getWeekNum();
        //获取当前时间对应的周时间段
        String weekTime = DateUtil.getWeekTime();
        for (StudentTeacher studentTeacher : studentTeacherList) {
            Weekly weekly = new Weekly();
            weekly.setStudentId(studentTeacher.getStudentId());
            weekly.setSemesterId(studentTeacher.getSemesterId());
            weekly.setWeek(weekNum);
            weekly.setWeekTime(weekTime);
            weekly.setAgencyId(agencyId);
            //获取关联教师信息
            Integer practicalTeacherId = ObjectUtils.isEmpty(studentTeacher.getPracticalTeacherId()) ? studentTeacher.getHonoraryTeacherId() : studentTeacher.getPracticalTeacherId();
            weekly.setPracticalTeacherId(practicalTeacherId);
            weekly.setHonoraryTeacherId(studentTeacher.getHonoraryTeacherId());
            weekly.setStatus(WEEKLY_NOT_SUBMIT);
            weekly.setUpdater(INITIALIZE_UPDATE_ADMIN);
            Weekly weeklyInfo = getWeeklyInfo(studentTeacher.getSemesterId(), weekNum, studentTeacher.getStudentId());
            if (ObjectUtils.isNotEmpty(weeklyInfo)) {
                continue;
            } else {
                boolean save = save(weekly);
                if (!save) {
                    throw new RuntimeException("组织{" + agencyId + "}新增周报失败");
                }
            }
            //项目信息
            List<UserProject> studentProjectList = userProjectService.getStudentProjectList(studentTeacher.getStudentId(), studentTeacher.getSemesterId());
            if (CollectionUtils.isNotEmpty(studentProjectList)) {
                studentProjectList.forEach(f -> {
                    WeeklyProject weeklyProject = new WeeklyProject();
                    weeklyProject.setWeeklyId(weekly.getId());
                    weeklyProject.setProjectId(f.getProjectId());
                    weeklyProject.setUpdater(INITIALIZE_UPDATE_ADMIN);
                    weeklyProjectService.save(weeklyProject);
                });
            }
        }
        log.info("批量新增周报成功");
    }

    /**
     * 修改周报
     *
     * @param updateWeeklyDTO
     * @return
     */
    @Override
    public R<?> updateWeekly(UpdateWeeklyDTO updateWeeklyDTO) {
        UserVO userInfo = userService.getUserInfo();
        if (ObjectUtils.isEmpty(userInfo)) {
            return R.Failed("用户信息获取失败");
        }
        Weekly weekly = getById(updateWeeklyDTO.getId());
        if (ObjectUtils.isEmpty(weekly)) {
            return R.Failed("未能找到需要修改的周报信息");
        }
        if (!(weekly.getStatus().equals(WEEKLY_NOT_REVIEW) || weekly.getStatus().equals(WEEKLY_NOT_SUBMIT))) {
            return R.Failed("周报不符合要求，不能填写周报");
        }
        BeanUtils.copyProperties(updateWeeklyDTO, weekly);
        if (weekly.getStatus().equals(WEEKLY_NOT_SUBMIT)) {
            weekly.setStatus(WEEKLY_NOT_REVIEW);
        }
        boolean update = updateById(weekly);
        if (!update) {
            return R.Failed("周报修改失败");
        }
        return R.Success("周报修改成功", null);
    }

    /**
     * 周报评阅
     *
     * @param weeklyReviewDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public R<?> weeklyReview(WeeklyReviewDTO weeklyReviewDTO) {
        UserVO userInfo = userService.getUserInfo();
        if (ObjectUtils.isEmpty(userInfo)) {
            return R.Failed("用户信息获取失败");
        }
        Weekly weekly = getById(weeklyReviewDTO.getWeeklyId());
        if (weekly == null) {
            return R.Failed("未能找到需要评语的周报信息");
        }
        if (!(weekly.getStatus().equals(WEEKLY_NOT_REVIEW) || weekly.getStatus().equals(WEEKLY_REVIEW))) {
            return R.Failed("周报不符合要求，不能评阅");
        }
        if (weekly.getAppraiseId() != null) {
            Appraise appraise = appraiseService.getById(weekly.getAppraiseId());
            appraise.setContent(weeklyReviewDTO.getAppraiseInfo());
            boolean update = appraiseService.updateById(appraise);
            if (!update) {
                return R.Failed("周报评阅失败-修改评阅信息失败");
            }
        } else {
            Appraise appraise = new Appraise();
            appraise.setContent(weeklyReviewDTO.getAppraiseInfo());
            boolean save = appraiseService.save(appraise);
            if (!save) {
                return R.Failed("周报评阅失败-首次评阅失败");
            }
            weekly.setAppraiseId(appraise.getId());
        }
        if (weekly.getStatus().equals(WEEKLY_NOT_REVIEW)) {
            weekly.setStatus(WEEKLY_REVIEW);
        }
        boolean update = updateById(weekly);
        if (!update) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.Failed("周报评阅失败-修改评阅状态和信息失败");
        }
        if (weeklyReviewDTO.getUpdateEvaluateDTO() != null) {
            UpdateEvaluateDTO updateEvaluateDTO = weeklyReviewDTO.getUpdateEvaluateDTO();
            Evaluate evaluate = evaluateService.getById(updateEvaluateDTO.getId());
            if (evaluate == null) {
                return R.Failed("未能找到需要修改的评语信息");
            }
            BeanUtils.copyProperties(updateEvaluateDTO, evaluate);
            evaluate.setTotalScore(evaluate.getCodeQualityScore() + evaluate.getInitiativeScore() + evaluate.getTaskCompletionScore() + evaluate.getWorkingAttitudeScore());
            boolean updateEvaluate = evaluateService.updateById(evaluate);
            if (!updateEvaluate) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.Failed("周报评阅失败-修改评语信息失败");
            }
        }
        return R.Success("周报评阅成功", null);
    }

    /**
     * 周报分页查询
     *
     * @param weeklyPageDTO
     * @return
     */
    @Override
    public R<PageVO<WeeklyPageVO>> getWeeklyByPage(WeeklyPageDTO weeklyPageDTO) {
        // 开启分页
        Page<Weekly> page = new Page<>(weeklyPageDTO.getPageNo(), weeklyPageDTO.getPageSize());
        //当查询条件执行过程中未找到数据时返回当前结果
        Page<Weekly> nullWeeklyPage = page(page);
        PageVO nullWeeklyPageVO = BeanCopyUtil.copy(nullWeeklyPage, PageVO.class);
        nullWeeklyPageVO.setRecords(null);
        //未指定组织信息时为空
        if (ObjectUtils.isEmpty(weeklyPageDTO.getAgencyId())) {
            log.error("未指定组织信息");
            return R.Success(nullWeeklyPageVO);
        }
        UserVO userInfo = userService.getUserInfo();
        boolean isOwnAgencyWeekly = userInfo.getUserResource().stream().anyMatch(resourceVO -> resourceVO.getResourcePath().equals(PermissionConst.GET_OWN_AGENCY_WEEKLY));
        //当登录账户为学生时，就优先查询学生周报，如果不是就根据学生姓名模糊查询
        List<RoleVO> roles = userInfo.getRoles();
        boolean isStudent = roles.stream().anyMatch(role -> role.getId().equals(STUDENT));
        List<Integer> studentIds = new ArrayList<>();
        if (isStudent && !isOwnAgencyWeekly) {
            studentIds.add(UserUtil.getCurrentUser().getId());
        } else {
            if (StringUtils.isNotBlank(weeklyPageDTO.getStudentName())) {
                List<User> studentList = userService.getUserListByUserName(weeklyPageDTO.getStudentName());
                if (CollectionUtils.isEmpty(studentList)) {
                    return R.Success(nullWeeklyPageVO);
                }
                studentIds = studentList.stream().map(User::getId).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(studentIds)) {
                    return R.Success(nullWeeklyPageVO);
                }
            }
        }
        //模糊查询实际教师
        List<Integer> teacherIds = new ArrayList<>();
        //角色为教师的则获取当前教师信息，不为教师的则模糊查询
        boolean isTeacher = roles.stream().anyMatch(role -> role.getId().equals(TEACHER));
        if (isTeacher && !isOwnAgencyWeekly) {
            teacherIds.add(userInfo.getId());
        } else {
            //根据教师姓名模糊查询
            if (StringUtils.isNotBlank(weeklyPageDTO.getPracticalTeacherName())) {
                List<User> teacherList = userService.getUserListByUserName(weeklyPageDTO.getPracticalTeacherName());
                if (CollectionUtils.isEmpty(teacherList)) {
                    return R.Success(nullWeeklyPageVO);
                }
                teacherIds = teacherList.stream().map(User::getId).collect(Collectors.toList());
            }
        }
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CollectionUtils.isNotEmpty(studentIds), Weekly::getStudentId, studentIds)
                .eq(Weekly::getAgencyId, weeklyPageDTO.getAgencyId())
                .eq(Weekly::getSemesterId, weeklyPageDTO.getSemesterId())
                .eq(ObjectUtils.isNotEmpty(weeklyPageDTO.getWeek()), Weekly::getWeek, weeklyPageDTO.getWeek())
                .eq(ObjectUtils.isNotEmpty(weeklyPageDTO.getStatus()), Weekly::getStatus, weeklyPageDTO.getStatus())
                .in(CollectionUtils.isNotEmpty(teacherIds), Weekly::getPracticalTeacherId, teacherIds)
                .orderByDesc(Weekly::getUpdateTime);
        Page<Weekly> weeklyPage = page(page, queryWrapper);
        PageVO weeklyPageVO = BeanCopyUtil.copy(weeklyPage, PageVO.class);
        List<WeeklyPageVO> weeklyPageVOList = new ArrayList<>();
        weeklyPage.getRecords().forEach(weekly -> {
            WeeklyPageVO weeklyVO = BeanCopyUtil.copy(weekly, WeeklyPageVO.class);
            User student = userService.getById(weekly.getStudentId());
            weeklyVO.setStudentAccount(student.getUsername());
            weeklyVO.setStudentName(student.getFullName());
            User user = userService.getById(weekly.getPracticalTeacherId());
            weeklyVO.setPracticalTeacherAccount(user.getUsername());
            weeklyVO.setPracticalTeacherName(user.getFullName());
            weeklyPageVOList.add(weeklyVO);
        });
        weeklyPageVO.setRecords(weeklyPageVOList);
        return R.Success(weeklyPageVO);
    }

    /**
     * 根据id获取周报信息
     *
     * @param weeklyId
     * @return
     */
    @Override
    public R<WeeklyAppraiseVO> getWeeklyById(Integer weeklyId) {
        UserVO userInfo = userService.getUserInfo();
        if (ObjectUtils.isEmpty(userInfo)) {
            return R.Failed("用户信息获取失败");
        }
        Weekly weekly = getById(weeklyId);
        if (ObjectUtil.isNull(weekly)) {
            return R.Failed(DB_GET_DATA_FAIL.getCode(), "根据周报id获取周报信息为空");
        }
        WeeklyAppraiseVO weeklyAppraiseVO = BeanCopyUtil.copy(weekly, WeeklyAppraiseVO.class);
        //获取学生姓名
        User studentInfo = userService.getById(weekly.getStudentId());
        if (ObjectUtils.isEmpty(studentInfo)) {
            return R.Failed(DB_GET_DATA_FAIL.getCode(), "查询周报详情失败-未能找到周报的学生信息");
        }
        weeklyAppraiseVO.setStudentName(studentInfo.getFullName());
        //获取学期信息
        Semester semester = semesterService.getById(weekly.getSemesterId());
        if (ObjectUtils.isEmpty(semester)) {
            return R.Failed(DB_GET_DATA_FAIL.getCode(), "查询周报详情失败-未能找到对应的学期信息");
        }
        weeklyAppraiseVO.setSemesterName(semester.getName());
        //获取项目信息
        List<ProjectVO> projectVOS = weeklyProjectService.getProjectByWeeklyId(weeklyId);
        weeklyAppraiseVO.setProject(projectVOS);
        //获取教师评价
        if (ObjectUtils.isNotEmpty(weekly.getAppraiseId())) {
            Appraise appraise = appraiseService.getById(weekly.getAppraiseId());
            weeklyAppraiseVO.setAppraiseInfo(appraise.getContent());
        }
        //获取学生评分
        Evaluate evaluate = evaluateService.getByWeeklyId(weeklyId);
        if (ObjectUtils.isNotEmpty(evaluate)) {
            WeeklyEvaluateVO weeklyEvaluateVO = BeanCopyUtil.copy(evaluate, WeeklyEvaluateVO.class);
            weeklyAppraiseVO.setEvaluate(weeklyEvaluateVO);
        }
        return R.Success(weeklyAppraiseVO);
    }


    /**
     * 获取当前学期周数
     *
     * @return
     */
    @Override
    public R<List<Integer>> getWeekNum(Integer semesterId) {
        Semester semester = semesterService.getById(semesterId);
        if (ObjectUtils.isEmpty(semester)) {
            return R.Success();
        }
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Weekly::getSemesterId, semester.getId());
        List<Weekly> list = list(queryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            List<Integer> weekNumList = list.stream().map(Weekly::getWeek).distinct().collect(Collectors.toList());
            return R.Success(weekNumList);
        }
        return R.Success();
    }

    /**
     * 根据学期id、周数、学生id获取当前周报信息
     *
     * @param semesterId
     * @param weekNum
     * @param studentId
     * @return
     */
    @Override
    public Weekly getWeeklyInfo(Integer semesterId, Integer weekNum, Integer studentId) {
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Weekly::getSemesterId, semesterId)
                .eq(Weekly::getWeek, weekNum)
                .eq(Weekly::getStudentId, studentId);
        return getOne(queryWrapper);
    }

    /**
     * 获取学生上一周的项目
     *
     * @param semesterId
     * @param weekNum
     * @param studentId
     * @return
     */
    @Override
    public List<WeeklyProject> getLastWeeklyProjectId(Integer semesterId, Integer weekNum, Integer studentId) {
        int lastWeekNum;
        if (weekNum.equals(1)) {
            lastWeekNum = weekNum;
        } else {
            lastWeekNum = weekNum - 1;
        }
        Weekly lastWeeklyInfo = getWeeklyInfo(semesterId, lastWeekNum, studentId);
        if (ObjectUtils.isEmpty(lastWeeklyInfo)) {
            return new ArrayList<>();
        }
        return weeklyProjectService.getByWeeklyId(lastWeeklyInfo.getId());
    }

    /**
     * 获取学生未绑定教师的周报信息
     *
     * @param studentId
     * @param semesterId
     * @return
     */
    @Override
    public List<Weekly> getNoTeacherWeeklyList(Integer studentId, Integer semesterId) {
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Weekly::getStudentId, studentId)
                .eq(Weekly::getSemesterId, semesterId)
                .isNull(Weekly::getHonoraryTeacherId)
                .isNull(Weekly::getHonoraryTeacherId);
        return list(queryWrapper);
    }

    /**
     * 获取当前组织下学期内本周的周报信息
     *
     * @param semesterId
     * @param agencyId
     * @return
     */
    @Override
    public List<Weekly> getWeeklyList(Integer semesterId, Integer agencyId) {
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<Weekly>()
                .eq(Weekly::getAgencyId, agencyId)
                .eq(Weekly::getSemesterId, semesterId)
                .eq(Weekly::getWeek, semesterService.getWeekNum());
        return list(queryWrapper);
    }

    /**
     * 根据实际教师获取指定周内的周报
     *
     * @param semesterId
     * @param practicalTeacherId
     * @param weekNum
     * @return
     */
    @Override
    public List<Weekly> getWeeklyListByPracticalTeacherId(Integer semesterId, Integer practicalTeacherId, Integer weekNum) {
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Weekly::getSemesterId, semesterId)
                .eq(Weekly::getPracticalTeacherId, practicalTeacherId)
                .eq(Weekly::getWeek, weekNum);
        return list(queryWrapper);
    }

    /**
     * 根据名誉教师获取指定周内的周报
     *
     * @param semesterId
     * @param honoraryTeacherId
     * @param weekNum
     * @return
     */
    @Override
    public List<Weekly> getWeeklyListByHonoraryTeacherId(Integer semesterId, Integer honoraryTeacherId, Integer weekNum) {
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Weekly::getSemesterId, semesterId)
                .eq(Weekly::getHonoraryTeacherId, honoraryTeacherId)
                .eq(Weekly::getWeek, weekNum);
        return list(queryWrapper);
    }

    /**
     * 获取当前教师对应学生的周评价信息
     *
     * @param weekNum
     * @param honoraryTeacherId
     * @param semesterId
     * @return
     */
    @Override
    public String getAppraise(Integer semesterId, Integer honoraryTeacherId, Integer weekNum) {
        List<Weekly> weeklyList = getWeeklyListByHonoraryTeacherId(semesterId, honoraryTeacherId, weekNum);
        StringBuilder result = new StringBuilder();
        if (CollectionUtils.isEmpty(weeklyList)) {
            return result.toString();
        }
        for (Weekly weekly : weeklyList) {
            User student = userService.getById(weekly.getStudentId());
            if (ObjectUtils.isEmpty(student)) {
                return result.toString();
            }
            Evaluate evaluate = evaluateService.getByWeeklyId(weekly.getId());
            if (ObjectUtils.isEmpty(evaluate)) {
                return result.toString();
            }
            result.append(student.getFullName()).append("：").append(evaluate.getEvaluationDescription()).append("\n");
        }
        return result.toString();
    }

    /**
     * 获取Excel学生周评分表信息
     *
     * @param dto
     * @return
     */
    @Override
    public R<?> createEvaluateFile(DownloadFileDTO dto) {
        //获取学期信息
        Semester semester = semesterService.getById(dto.getSemesterId());
        if (null == semester) {
            return R.Failed("未找到当前学期");
        }
        //学年学期
        String semesterName = semester.getName();
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(Weekly::getWeek, dto.getBeginWeekNum())
                .le(Weekly::getWeek, dto.getEndWeekNum())
                .eq(Weekly::getSemesterId, dto.getSemesterId())
                .eq(Weekly::getAgencyId, dto.getAgencyId())
                .eq(Weekly::getStatus, WEEKLY_REVIEW);
        List<Weekly> weeklyList = list(queryWrapper);
        if (CollectionUtils.isEmpty(weeklyList)) {
            return R.Failed("未找到对应的周报信息");
        }
        Map<Integer, List<Weekly>> map = weeklyList.stream().collect(Collectors.groupingBy(Weekly::getStudentId));
        Iterator<Map.Entry<Integer, List<Weekly>>> entries = map.entrySet().iterator();
        while (entries.hasNext()) {
            WeeklyEvaluateDTO weeklyEvaluateDto = new WeeklyEvaluateDTO();
            Map.Entry<Integer, List<Weekly>> entry = entries.next();
            Integer studentId = entry.getKey();
            //学生信息
            User studentInfo = userService.getById(studentId);
            if (ObjectUtil.isEmpty(studentInfo)) {
                log.error("未找到学生{}的信息", studentId);
                continue;
            }
            weeklyEvaluateDto.setStudentAccount(studentInfo.getUsername());
            weeklyEvaluateDto.setStudentName(studentInfo.getFullName());
            //班级信息
            Clazz clazz = clazzService.getById(studentInfo.getClassId());
            weeklyEvaluateDto.setClassInfo(clazz.getClassName());
            //学期信息
            weeklyEvaluateDto.setSemesterName(semesterName);
            //教师姓名
            StudentTeacher studentTeacher = studentTeacherService.getByStudentId(studentId, dto.getSemesterId());
            if (ObjectUtil.isEmpty(studentTeacher)) {
                log.error("未找到学生{}学期学生教师关联关系", studentId);
                continue;
            }
            User teacherInfo = userService.getById(studentTeacher.getHonoraryTeacherId());
            if (ObjectUtil.isEmpty(teacherInfo)) {
                log.error("未找到名誉教师{}的信息", studentTeacher.getHonoraryTeacherId());
                continue;
            }
            String teacherName = teacherInfo.getFullName();
            weeklyEvaluateDto.setTeacherName(teacherName);
            List<EvaluateExcelDTO> evaluateExcelDtos = entry.getValue().stream().map(weekly -> {
                EvaluateExcelDTO evaluateExcelDto = new EvaluateExcelDTO();
                //周评分信息
                Evaluate teacherEvaluate = evaluateService.getByWeeklyId(weekly.getId());
                if (ObjectUtil.isEmpty(teacherEvaluate)) {
                    log.error("学生{}第{}周未进行周评分，周报id是{}", studentInfo.getFullName(), weekly.getWeek(), weekly.getId());
                } else {
                    BeanUtils.copyProperties(teacherEvaluate, evaluateExcelDto);
                }
                //周数
                evaluateExcelDto.setWeekNum(weekly.getWeek());
                //时间
                String[] weekTime = weekly.getWeekTime().split("~");
                LocalDate startTime = LocalDate.parse(weekTime[0], DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                LocalDate endTime = LocalDate.parse(weekTime[1], DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                String weeklyDateTime = startTime.getMonthValue() + "." + startTime.getDayOfMonth() + "-" +
                        endTime.getMonthValue() + "." + endTime.getDayOfMonth();
                evaluateExcelDto.setWeeklyDateTime(weeklyDateTime);
                //教师名称
                evaluateExcelDto.setTeacherName(teacherName);
                //项目名称
                List<ProjectVO> projectVOList = weeklyProjectService.getProjectByWeeklyId(weekly.getId());
                String projectName = projectVOList.stream().map(ProjectVO::getProjectName).collect(Collectors.toList()).toString()
                        .replace("[", "").replace("]", "")
                        .replace("\"", "").replace(",", "、");
                evaluateExcelDto.setProjectName(projectName);
                //指导教师签名
                evaluateExcelDto.setTeacherSignature(StringUtils.isBlank(teacherInfo.getSignature()) ? null : teacherInfo.getSignature());
                return evaluateExcelDto;
            }).collect(Collectors.toList());
            weeklyEvaluateDto.setEvaluateExcelDtoList(evaluateExcelDtos);
            //生成映射数据
            String fileName = weeklyEvaluateDto.getStudentAccount() + "-" + weeklyEvaluateDto.getStudentName()
                    + "-周打分（" + weeklyEvaluateDto.getTeacherName() + "）.xlsx";
            String classInfoName = weeklyEvaluateDto.getClassInfo() + "/";
            String weeklyPathName = weeklyEvaluateDto.getStudentAccount() + "-" + weeklyEvaluateDto.getStudentName() + "/";
            String filePathElectronic = DEFAULT_FILE_PATH + DEFAULT_GUIDANCE_EVALUATE_PATH + classInfoName + weeklyPathName + fileName;
            ExcelUtil.createExcel(filePathElectronic, weeklyEvaluateDto);
            //纸质版路径
            String filePathPaper = DEFAULT_FILE_PATH + DEFAULT_GUIDANCE_EVALUATE_PATH + classInfoName + DEFAULT_EVALUATE_PATH + fileName;
            ExcelUtil.createExcel(filePathPaper, weeklyEvaluateDto);
        }
        return R.Success();
    }

    /**
     * 生成周报文件
     *
     * @param dto
     * @return
     */
    @Override
    public R<?> createWeeklyFile(DownloadFileDTO dto) {
        //获取学期信息
        Semester semester = semesterService.getById(dto.getSemesterId());
        if (null == semester) {
            return R.Failed("未找到当前学期");
        }
        //学年学期
        String semesterName = semester.getName();
        LambdaQueryWrapper<Weekly> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(Weekly::getWeek, dto.getBeginWeekNum())
                .le(Weekly::getWeek, dto.getEndWeekNum())
                .eq(Weekly::getSemesterId, dto.getSemesterId())
                .eq(Weekly::getAgencyId, dto.getAgencyId())
                .eq(Weekly::getStatus, WEEKLY_REVIEW);
        List<Weekly> weeklyList = list(queryWrapper);
        if (CollectionUtils.isEmpty(weeklyList)) {
            return R.Failed("未找到对应的周报信息");
        }
        Map<Integer, List<Weekly>> weeklyGroupMap = weeklyList.stream().collect(Collectors.groupingBy(Weekly::getStudentId));
        try {
            weeklyGroupMap.forEach((studentId, weeklyByStudentId) -> {
                User studentInfo = userService.getById(studentId);
                //班级信息
                Clazz clazz = clazzService.getById(studentInfo.getClassId());
                String classInfoName = clazz.getClassName() + "/";
                weeklyByStudentId.forEach(weekly -> {
                    User teacherInfo = userService.getById(weekly.getHonoraryTeacherId());
                    Map<String, Object> weeklyMapData = studentWeeklyMapData(studentInfo, weekly, semesterName, teacherInfo);
                    //文件名
                    String fileName = studentInfo.getUsername() + "-" + studentInfo.getFullName() +
                            "-第" + weekly.getWeek() + "周周报（" + teacherInfo.getFullName() + "）" + ".docx";
                    String filePath = DEFAULT_FILE_PATH + DEFAULT_WEEKLY_PATH + classInfoName + studentInfo.getUsername() + "-" + studentInfo.getFullName() + "/" + fileName;
                    XWPFUtil.createWeeklyWord(filePath, weeklyMapData);
                });

            });
        } catch (Exception e) {
            return R.Failed("生成学生周报失败：" + e.getMessage());
        }
        return R.Success();
    }

    /**
     * 生成周报映射数据
     *
     * @param studentInfo
     * @param weekly
     * @param semesterName
     * @return
     */
    public Map<String, Object> studentWeeklyMapData(User studentInfo, Weekly weekly, String semesterName, User teacherInfo) {
        Map<String, Object> params = new HashMap<>();
        params.put("${semesterName}", semesterName);
        params.put("${studentName}", studentInfo.getFullName());
        params.put("${studentAccount}", studentInfo.getUsername());
        params.put("${teacherName}", teacherInfo.getFullName());
        //学生项目名称
        List<ProjectVO> projectVOS = weeklyProjectService.getProjectByWeeklyId(weekly.getId());
        String projectName = projectVOS.stream().map(ProjectVO::getProjectName).collect(Collectors.toList()).toString()
                .replace("[", "").replace("]", "")
                .replace("\"", "").replace(",", "、");
        params.put("${projectName}", projectName);
        //学生选择岗位方向
        Position position = positionService.getById(studentInfo.getPositionId());
        params.put("${studentPort}", position.getName());
        //获取当前周信息
        params.put("${weekNum}", weekly.getWeek().toString());
        String[] weekTime = weekly.getWeekTime().split("~");
        params.put("${beginTime}", weekTime[0]);
        params.put("${endTime}", weekTime[weekTime.length - 1]);
        params.put("${developmentProject}", weekly.getTaskComplete());
        params.put("${learningTaskCompletion}", weekly.getLearningTaskCompletion());
        params.put("${encounterProblem}", weekly.getProblemsAndSolutions());
        params.put("${harvest}", weekly.getHarvest());
        params.put("${plan}", weekly.getPlan());
        Appraise appraise = appraiseService.getById(weekly.getAppraiseId());
        params.put("${teacherNote}", appraise.getContent());
        return params;
    }
}
